package us.codecraft.webmagic.processor.example;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.alibaba.fastjson.JSONObject;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.ResultItemsCollectorPipeline;
import us.codecraft.webmagic.processor.PageProcessor;

public class HotelGGPageProcessor implements PageProcessor {

	private static final String searchKeyWord = "iiiitwmwjwrwuwf";//"ijjmiiitwm"; // 苏州5星
	private static final Integer pageNum = 1009;
	private static final String saveFileUrl = "d:\\webmagic\\hotelgg.csv";
	// 部分一：抓取网站的相关配置，包括编码、抓取间隔、重试次数等
	private Site site = Site.me().setRetryTimes(5).setSleepTime(7000).setTimeOut(61000).setDomain("www.hotelgg.com")
			.addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
			.addHeader("Accept-Encoding", "gzip, deflate, sdch")
			.addHeader("Accept-Language", "en-US,en;q=0.8,zh-CN;q=0.6")
			.addHeader("Connection", "keep-alive")
			.addHeader("X-Requested-With", "XMLHttpRequest")
			.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36");
	
	private static Spider spider = null;
	private static Integer pageIndex = 1;// 记录分页起始位置，
	public static void main(String[] args) {
		HotelGGPageProcessor processor = new HotelGGPageProcessor();
		processor.initializeCookie(args);
		processor.initializePageUrl(pageNum);
		ResultItemsCollectorPipeline pipeline = new ResultItemsCollectorPipeline();
		spider = Spider.create(processor);
		// 开始抓取的页面
		spider.addUrl(processor.mapPageUrl.get(pageIndex)).addPipeline(pipeline);
		// 开启5个线程抓取
		spider.thread(1);
		// 启动爬虫
		spider.run();
		// 保存到表格
		processor.saveExcel(pipeline);
	}

	private void initializeCookie(String[] args) {
		for (int i = 0; i < args.length; i++) {
		   String[] cookie =args[i].replace(";", "").split("=");
		   if(cookie.length ==3 ){
			   getSite().addCookie(cookie[0], cookie[1]+cookie[2]);//有个别value含1个=号
		   }
		   else if(cookie.length ==1){
			   //value是空值，就不传了
		   }
		   else
			   getSite().addCookie(cookie[0], cookie[1]);
		}
	}

	private void saveExcel(ResultItemsCollectorPipeline pipeline) {
		// 第一步，创建一个workbook对应一个excel文件
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 第二部，在workbook中创建一个sheet对应excel中的sheet
		HSSFSheet sheet = workbook.createSheet("酒店哥哥会厅全套价格");
		// 第三部，在sheet表中添加表头第0行，老版本的poi对sheet的行列有限制
		HSSFRow row = sheet.createRow(0);
		// 第四步，创建单元格，设置表头
		HSSFCell cell = row.createCell(0);
		cell.setCellValue("hotelggId");
		cell = row.createCell(1);
		cell.setCellValue("hotelName");
		cell = row.createCell(2);
		cell.setCellValue("meetingGGID");
		cell = row.createCell(3);
		cell.setCellValue("meetingName");
		cell = row.createCell(4);
		cell.setCellValue("alldayPrice");
		cell = row.createCell(5);
		cell.setCellValue("halfPrice");

		// 第五步，写入实体数据
		List<ResultItems> resultItemsList = pipeline.getCollected();
		int index = 1;
		for (ResultItems item : resultItemsList) {
			if (item.get("hotel") != null) {
				HotelInfo hotel = (HotelInfo) item.get("hotel");
				for (MeetingInfo meeting : hotel.meetingInfos) {
					HSSFRow row1 = sheet.createRow(index++);
					// 创建单元格设值
					row1.createCell(0).setCellValue(hotel.getHotelggId());
					row1.createCell(1).setCellValue(hotel.getHotelName().replace("会场", ""));
					row1.createCell(2).setCellValue(meeting.getMeetingGGID());
					row1.createCell(3).setCellValue(meeting.getMeetingName());
					row1.createCell(4).setCellValue(meeting.getAlldayPrice());
					row1.createCell(5).setCellValue(meeting.getHalfPrice());
				}
			}
		}

		// 将文件保存到指定的位置
		try {
			FileOutputStream fos = new FileOutputStream(saveFileUrl);
			workbook.write(fos);
			System.out.println("写入成功");
			fos.close();
			workbook.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private  Map<Integer, String> mapPageUrl = new HashMap<Integer, String>();

	/*
	 * 酒店哥哥有数字加密，这里做下转义并直接生成分页地址
	 */
	private  void initializePageUrl(Integer pageNum) {
		Map<Integer, String> num2Word = new HashMap<Integer, String>();// 乱码对照数字表
		num2Word.put(0, "l");
		num2Word.put(1, "m");
		num2Word.put(2, "j");
		num2Word.put(3, "o");
		num2Word.put(4, "f");
		num2Word.put(5, "r");
		num2Word.put(6, "s");
		num2Word.put(7, "t");
		num2Word.put(8, "u");
		num2Word.put(9, "v");
		for (Integer i = 1; i < pageNum; i++) {
			Integer size = i.toString().length();
			String pageIndex = "";
			for (Integer j = 0; j < size; j++) {
				pageIndex += num2Word.get(Integer.valueOf(i.toString().substring(j, j + 1)));
			}
			pageIndex = "https://www.hotelgg.com/venue/" + pageIndex + searchKeyWord;
			mapPageUrl.put(i, pageIndex);
		}
	}

	@Override
	public void process(Page page)  {
		if (page.getUrl().get().contains(searchKeyWord)) {
			System.out.println("列表页获取内容页链接******************************");
			List<String> urls = page.getHtml().css("h3.title").links().all();
			if (urls.size() > 0) {
				urls.add(mapPageUrl.get(++pageIndex));// 有内容就继续翻页
			}
			page.addTargetRequests(urls);
		} else if (page.getUrl().get().contains("https://www.hotelgg.com/view-")) {
			System.out.println("内容页获取酒店信息及meetingid----------------------------------");
			initialHotelInfo(page);
		} else if (page.getUrl().get().contains("https://www.hotelgg.com/meetingroom/alldayprice/")) {
			System.out.println("会厅价格----------------------------------");
			setMeetingPrice(page);
		}
	}

	private static int searchInterval = 1;
	private void setMeetingPrice(Page page) {
		HotelInfo hotel = hotels.get(page.getUrl().toString());
		String originJson = page.getHtml().toString().replace("<html>", "").replace("<head>", "").replace("</head>", "")
				.replace("<body>", "").replace("</html>", "").replace("</body>", "").replace("\n", "")
				.replace("\\uffe5", "");
		JSONObject jsonData = JSONObject.parseObject(originJson).getJSONObject("data");
		if (jsonData !=null) {			
			System.out.println("反爬被激活，爬取到第" + pageIndex +"页");
			//关闭线程重新启动一个线程用其他账号继续从pageindex页继续爬
		}
		for (MeetingInfo room : hotel.getMeetingInfos()) {
			room.alldayPrice = ((JSONObject) jsonData.get(room.getMeetingGGID())).get("allday_price").toString();
			room.halfPrice = ((JSONObject) jsonData.get(room.getMeetingGGID())).get("halfday_price").toString();
		}
		page.putField("hotel", hotel);
	}

	public static Map<String, HotelInfo> hotels = new HashMap<String, HotelInfo>();

	/*
	 * 初始化构建酒店信息基础 Map<PriceUrl,HotelInfo>
	 */
	private void initialHotelInfo(Page page) {
		HotelInfo hotel = new HotelInfo();
		// 1、获取酒店内容页中酒店级信息，如id，name , star等
		hotel.hotelggId = page.getUrl().all().get(0).replaceAll("\\D", "");
		List<String> hotelName = page.getHtml().css("div.bread-crumbs").css("span", "text").all();
		hotel.hotelName = hotelName.isEmpty() ? "" : hotelName.get(0);

		// 2、实例会厅信息, 取酒店相关会厅价格数据页地址
		List<String> meetingNames = page.getHtml().css("div.mt_name").css("strong", "text").all();
		List<MeetingInfo> meetings = new ArrayList<MeetingInfo>();
		List<String> urls = page.getHtml().css("a.view_price_meetingroom", "data-meetingroom-id").all();
		StringBuilder getMeetingPriceUrl = new StringBuilder("https://www.hotelgg.com/meetingroom/alldayprice/");
		for (int i = 0; i < urls.size(); i++) {
			MeetingInfo meeting = new MeetingInfo();
			meeting.meetingGGID = urls.get(i);
			getMeetingPriceUrl.append(urls.get(i)).append((i < urls.size() - 1) ? "," : "");
			meeting.meetingName = meetingNames.get(i);
			meetings.add(meeting);
		}
		page.addTargetRequest(getMeetingPriceUrl.toString());
		hotel.meetingInfos = new ArrayList<MeetingInfo>();
		hotel.meetingInfos.addAll(meetings);

		// 3、getmeetingPriceUrl用做字典的key值，方便获取价格后快速查找对应酒店对象。
		hotels.put(getMeetingPriceUrl.toString(), hotel);
		;
	}

	@Override
	public Site getSite() {
		return site;
	}
}
